package net.airtheva.hexagonMatrix;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;

import javax.microedition.khronos.opengles.GL10;

import net.airtheva.hexagonMatrix.data.Matrix4x4f;
import net.airtheva.hexagonMatrix.data.Plane;
import net.airtheva.hexagonMatrix.data.Vector2f;
import net.airtheva.hexagonMatrix.data.Vector3f;
import net.airtheva.hexagonMatrix.data.Vector4f;
import net.airtheva.hexagonMatrix.data.Vertex;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLUtils;
import android.util.Log;
import android.view.View;

public class Hexagon extends BaseComponent {

	public static final int STATUS_IDLE = 0;
	public static final int STATUS_ACTIVE = 1;
	public static final int STATUS_BUSY = 2;
	
	Vertex[] mVertices;
	short[] mIndices;
	
	FloatBuffer mPositionBuffer;
	FloatBuffer mColorBuffer;
	FloatBuffer mTexCoordBuffer;
	ShortBuffer mIndexBuffer;
	
	IntBuffer mTextureBuffer;
	
	public Hexagon(Surface surface) {
		// TODO Auto-generated constructor stub
		super(surface);
		mVertices = new Vertex[] {
			(new Vertex()).Position(0.0f, 0.0f, 0.0f).Color(1.0f, 1.0f, 1.0f, 1.0f).TexCoord(0.5f, 0.5f), // Center.
			(new Vertex()).Position((float) Math.cos(Math.toRadians(30)) * 0.9f, (float) Math.sin(Math.toRadians(30)) * 0.9f, 0.0f).Color(0.8f, 0.8f, 0.8f, 1.0f).TexCoord(1.0f, 0.0f),
			(new Vertex()).Position((float) Math.cos(Math.toRadians(90)) * 0.9f, (float) Math.sin(Math.toRadians(90)) * 0.9f, 0.0f).Color(0.8f, 0.8f, 0.8f, 1.0f).TexCoord(0.5f, 0.0f),
			(new Vertex()).Position((float) Math.cos(Math.toRadians(150)) * 0.9f, (float) Math.sin(Math.toRadians(150)) * 0.9f, 0.0f).Color(0.8f, 0.8f, 0.8f, 1.0f).TexCoord(0.0f, 0.0f),
			(new Vertex()).Position((float) Math.cos(Math.toRadians(210)) * 0.9f, (float) Math.sin(Math.toRadians(210)) * 0.9f, 0.0f).Color(0.8f, 0.8f, 0.8f, 1.0f).TexCoord(0.0f, 1.0f),
			(new Vertex()).Position((float) Math.cos(Math.toRadians(270)) * 0.9f, (float) Math.sin(Math.toRadians(270)) * 0.9f, 0.0f).Color(0.8f, 0.8f, 0.8f, 1.0f).TexCoord(0.5f, 1.0f),
			(new Vertex()).Position((float) Math.cos(Math.toRadians(330)) * 0.9f, (float) Math.sin(Math.toRadians(330)) * 0.9f, 0.0f).Color(0.8f, 0.8f, 0.8f, 1.0f).TexCoord(1.0f, 1.0f),
			(new Vertex()).Position((float) Math.cos(Math.toRadians(30)), (float) Math.sin(Math.toRadians(30)), 0.0f).Color(0.8f, 0.8f, 0.8f, 1.0f),
			(new Vertex()).Position((float) Math.cos(Math.toRadians(90)), (float) Math.sin(Math.toRadians(90)), 0.0f).Color(0.8f, 0.8f, 0.8f, 1.0f),
			(new Vertex()).Position((float) Math.cos(Math.toRadians(150)), (float) Math.sin(Math.toRadians(150)), 0.0f).Color(0.8f, 0.8f, 0.8f, 1.0f),
			(new Vertex()).Position((float) Math.cos(Math.toRadians(210)), (float) Math.sin(Math.toRadians(210)), 0.0f).Color(0.8f, 0.8f, 0.8f, 1.0f),
			(new Vertex()).Position((float) Math.cos(Math.toRadians(270)), (float) Math.sin(Math.toRadians(270)), 0.0f).Color(0.8f, 0.8f, 0.8f, 1.0f),
			(new Vertex()).Position((float) Math.cos(Math.toRadians(330)), (float) Math.sin(Math.toRadians(330)), 0.0f).Color(0.8f, 0.8f, 0.8f, 1.0f)
		};
		
		mIndices = new short[] {
			0, 1, 2,
			0, 2, 3,
			0, 3, 4,
			0, 4, 5,
			0, 5, 6,
			0, 6, 1, // Entry.
			7, 8, 9, 10, 11, 12 // Frame.
		};
		
		makeBuffer();
		
		SetOnClickListener(new BaseComponent.OnClickListener() {
			
			@Override
			public boolean onClick(Line pickingRay) {
				// TODO Auto-generated method stub
				Log.v("Hexagon", "Click.");
				return true;
			}
		});
		
	}
	
	@Override
	protected void makeBuffer() {
		
		mPositionBuffer = ByteBuffer.allocateDirect(mVertices.length * Vector3f.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
		mColorBuffer = ByteBuffer.allocateDirect(mVertices.length * Vector4f.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
		mTexCoordBuffer = ByteBuffer.allocateDirect(mVertices.length * Vector2f.SIZE).order(ByteOrder.nativeOrder()).asFloatBuffer();
		mIndexBuffer = ByteBuffer.allocateDirect(mIndices.length * Constants.SHORT_SIZE).order(ByteOrder.nativeOrder()).asShortBuffer();
		
		for(int i = 0; i < mVertices.length; i++) {
			Vertex vertex = mVertices[i];
			mPositionBuffer.put(vertex.Position.Data);
			mColorBuffer.put(vertex.Color.Data);
			mTexCoordBuffer.put(vertex.TexCoord.Data);
		}
		
		mIndexBuffer.put(mIndices);
		
		mPositionBuffer.position(0);
		mColorBuffer.position(0);
		mTexCoordBuffer.position(0);
		mIndexBuffer.position(0);
		
	}
	
	@Override
	protected Plane makePlane(Line pickingRay) {
		// TODO Auto-generated method stub
		Vertex point = new Vertex();
		point.Position(Matrix4x4f.Mult(ModelViewMatrix, new Vector3f(0.0f, 0.0f, 0.0f)));
		point.Position.Debug();
		
		return new Plane(point, new Vector3f(0.0f, 0.0f, 1.0f));
	}

	@Override
	protected boolean checkInclusion(Vertex point) {
		// TODO Auto-generated method stub
		
		Vertex center = mVertices[0];
		
		float length = (float) Math.sqrt(
			Math.pow(point.Position.Data[0] - center.Position.Data[0], 2) +
			Math.pow(point.Position.Data[1] - center.Position.Data[1], 2) +
			Math.pow(point.Position.Data[2] - center.Position.Data[2], 2)
		);
		
		if(length > 1) {
			return false;
		}
		
		return true;
	}

	@Override
	public void Draw(GL10 gl) {
		// TODO Auto-generated method stub
		
		if(mTextureBuffer == null) {
			mTextureBuffer = IntBuffer.allocate(1);
			gl.glGenTextures(1, mTextureBuffer);
			
			Bitmap texture;
			gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureBuffer.get(0));
			
			gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
			gl.glTexParameterx(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
			
			texture = Utils.LoadTexture(R.raw.hexagon);
			GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, texture, 0);
			
			gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
			
		}
		
		for(int i = 0; i < mColorBuffer.capacity(); i++) {
			float color = mColorBuffer.get(i);
			
			if(color >= 1.0f) {
				color = 0.0f;
			}
			else {
				color += 0.005f;
			}
			
			mColorBuffer.put(i, color);
		}
		
		preDraw(gl);
		
		//gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextureBuffer.get(0));
		
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, mPositionBuffer);
		gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
		gl.glColorPointer(4, GL10.GL_FLOAT, 0, mColorBuffer);
		gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTexCoordBuffer);

		mIndexBuffer.position(0);
		gl.glDrawElements(GL10.GL_TRIANGLES, 6 * 3, GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
		mIndexBuffer.position(6 * 3);
		gl.glDrawElements(GL10.GL_LINE_LOOP, 6, GL10.GL_UNSIGNED_SHORT, mIndexBuffer);
		
		gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
		gl.glDisableClientState(GL10.GL_COLOR_ARRAY);
		gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

		gl.glBindTexture(GL10.GL_TEXTURE_2D, 0);
		
	}
	
	public void AttachTo(Hexagon hexagon) {
		
	}

}
